package cn.chenli.job.service.impl;

import cn.chenli.job.constant.Constant;
import cn.chenli.job.dao.impl.QuartzJobDaoImpl;
import cn.chenli.job.model.QuartzJob;
import cn.chenli.job.service.QuartzJobService;
import cn.chenli.job.tool.engine.common.DynamicScriptEngine;
import cn.chenli.job.tool.engine.common.ToolEngineFactory;
import cn.chenli.job.tool.engine.java.Executor;
import cn.chenli.job.tool.engine.java.SimpleJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.spi.MutableTrigger;
import pro.tools.data.text.ToolStr;

import java.util.HashMap;
import java.util.Properties;

/**
 *
 * @author chenli
 * @create 2017-08-11
 */
public class QuartzJobServiceImpl extends BaseServiceImpl<QuartzJob> implements QuartzJobService {
    {
        super.setDao(new QuartzJobDaoImpl());
    }
    static Scheduler scheduler;
    static{
        /*创建一个StdSchedulerFactory实例*/
        StdSchedulerFactory factory = new StdSchedulerFactory();

         /*创建一个Properties类，来实现对工厂类的属性初始化*/
        Properties prop = new Properties();
        prop.put("org.quartz.scheduler.instanceName", "RenrenScheduler");
        prop.put("org.quartz.scheduler.instanceId", "AUTO");
        //线程池配置
        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
        prop.put("org.quartz.threadPool.threadCount", "10");
        prop.put("org.quartz.threadPool.threadPriority", "5");

        //JobStore配置
//        prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
        //集群配置
//        prop.put("org.quartz.jobStore.isClustered", "true");
//        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
//        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");

//        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
//        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");


//        prop.put(StdSchedulerFactory.PROP_THREAD_POOL_CLASS,"org.quartz.simpl.SimpleThreadPool");
//        prop.put("org.quartz.threadPool.threadCount", "10");

        try {
           /*根据属性信息初始化工厂类*/
            factory.initialize(prop);
            //获取一个任务调度器实例通过工厂类
            //启动该任务调度器，并执行上面注册的作业任务
            scheduler = factory.getScheduler();
        } catch (SchedulerException ex) {
            throw new RuntimeException();
        }
    }

    /**
     * 运行脚本
     * @param id：
     */
    public void execute(String id){
        QuartzJob quartzJob = super.findOne(new QuartzJob().setId(id));
        if(quartzJob == null){//代码逻辑这步不会走，除非高并发有人删库，但是作为定时器，这个基本不会存在，大型项目需要考虑
            throw new RuntimeException("没有该定时器");
        }
        DynamicScriptEngine engine = ToolEngineFactory.getEngine("java");//获取动态编译对象
        try {
            engine.execute(id,new HashMap<>());//执行脚本
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 编译脚本
     *
     * @param quartzJob：
     */
    private boolean compile(QuartzJob quartzJob){
        DynamicScriptEngine engine = ToolEngineFactory.getEngine("java");
        try {
            engine.compile(quartzJob.getId(),quartzJob.getScript());//编译脚本
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return Boolean.TRUE;
    }

    /**
     * 启动定时器
     * @param quartzJob：定时器
     */
    @Override
    public boolean enable(QuartzJob quartzJob) {
        if(!compile(quartzJob)) return Boolean.FALSE;//先执行校验是否可动态编译执行
        JobKey key = createJobKey(quartzJob.getId());//创建JobKey
        JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
                .withIdentity(key)
                .setJobData(new JobDataMap())
                .usingJobData(Constant.QUARTZ_JOB_ID_KEY, quartzJob.getId())
                .withDescription(quartzJob.getName() + (quartzJob.getRemark() == null ? "" : quartzJob.getRemark()))
                .build();
        MutableTrigger trigger = CronScheduleBuilder.cronSchedule(quartzJob.getCron()).build();
        trigger.setKey(createTriggerKey(quartzJob.getId()));
        try {
            scheduler.scheduleJob(jobDetail, trigger);
            scheduler.start();
            return Boolean.TRUE;
        } catch (SchedulerException e) {
            throw new RuntimeException("创建定时任务失败!");
        }
    }

    @Override
    public boolean stopJob(QuartzJob quartzJob) {
        deleteJob(quartzJob.getId());
        return true;
    }

    /**
     * 创建JobKey
     * @param jobId:
     */
    JobKey createJobKey(String jobId) {
        return new JobKey(jobId, "my.job.service");
    }

    /**
     * 创建TriggerKey
     * @param jobId:
     */
    TriggerKey createTriggerKey(String jobId) {
        return new TriggerKey(jobId, "my.job.service");
    }

    /**
     * 删除定时任务
     * @param id：删除id
     */
    void deleteJob(String id) {
        JobKey jobKey = createJobKey(id);
        try {
            if (scheduler.checkExists(jobKey)) {
                scheduler.deleteJob(jobKey);
            }
        } catch (SchedulerException e) {
            throw new RuntimeException("更新任务失败");
        }
    }
}